<script setup lang="ts">
import { Bottom, Close, Delete, Plus, Top, Warning } from '@element-plus/icons-vue'
import { formatOptions, formComponentProps, formComponents } from '@/utils/custom'
import { ElMessage } from 'element-plus'
import { nextTick, ref, watch } from 'vue'
import { findTree } from 'xe-utils'
import type {
  BusinessUIQueryType,
  BusinessUIQueryColumnType,
  FormComponentProp,
  IFListColumnType
} from '@/types/custom'

interface Props {
  params: BusinessUIQueryType
  columns: IFListColumnType[]
  business: RouteItems
  onEditJson: (parse?: any, key?: string) => {}
}

const props = defineProps<Props>()

const emit = defineEmits(['remove', 'select-component'])

// 环境
const VITE_ENV = import.meta.env.VITE_ENV

const active = ref('')
const activeName = ref('')
const set_json_parse_key = ref('')
const set_json_parse_value = ref('')
const restaurants = ref<FormComponentProp[]>(formComponentProps)
const formComponentOptions = formComponents.filter((f) =>
  f.hide ? f.hide && f.show?.includes(VITE_ENV) : true
)
const customComponents = ['custom-business', 'custom-business-form', 'custom-selector']

/**
 * 交换位置
 * @param arr
 * @param index1
 * @param index2
 */
function swapArrayElements(arr: BusinessUIQueryColumnType[], index1: number, index2: number) {
  arr[index1] = arr.splice(index2, 1, arr[index1])[0]
  return arr
}

/**
 * 排序
 * @param diff
 * @param index
 */
const onSplice = (diff: number, index: number) => {
  active.value = props.params.items[index].field
  swapArrayElements(props.params.items, index, index + diff)
}

/**
 * 选择组件
 * @param value
 * @param form
 */
const onSelectComponent = (value: string[], form: BusinessUIQueryColumnType) => {
  if (value.length) {
    const val = value[value.length - 1]
    const item = findTree(formComponents, (v) => v.value === val)
    if (item && item.item) {
      form.title = item.item.title || form.title
      form.elComponent = item.item.elComponent
      form.options = item.item.options
    }
    form.component = val
    // form.is_api = apiComponents.includes(form.component);
  } else {
    form.component = ''
  }
  emit('select-component', form.component, form)
}

/**
 * 排序
 * @param index
 */
const onDeleteForm = (index: number) => {
  emit('remove', index)
}

/**
 * 新增参数
 * @param form
 */
const addProp = (form: BusinessUIQueryColumnType) => {
  const keys = Object.keys(form.set_json_parse.props)
  if (set_json_parse_key.value) {
    if (keys.includes(set_json_parse_key.value)) {
      ElMessage.warning('属性名已存在')
    } else {
      form.set_json_parse.props[set_json_parse_key.value] = set_json_parse_value.value
    }
  } else {
    ElMessage.warning('请输入属性名')
  }
}

/**
 * 删除参数
 * @param form
 * @param key
 */
const onDeleteProp = (form: BusinessUIQueryColumnType, key: string) => {
  delete form.set_json_parse.props[key]
}

/**
 * 获取文档地址
 */
const getDocument = (form: BusinessUIQueryColumnType) => {
  const item = findTree(formComponents, (f) => f.value === form.component)
  if (item && item.item) {
    return item.item.document
  }
  return ''
}

/**
 * 查询
 * @param queryString
 * @param cb
 */
const querySearch = (queryString: string, cb: (results: FormComponentProp[]) => any) => {
  const results: FormComponentProp[] = queryString
    ? restaurants.value.filter(createFilter(queryString))
    : restaurants.value
  // call callback function to return suggestions
  cb(results)
}

/**
 * 选择属性附带默认值
 * @param item
 */
const onQuerySelect = (item: FormComponentProp) => {
  set_json_parse_value.value = item.default_value || ''
}

const querySearch2List: SelectOptionType[] = []

/**
 * 查询
 * @param queryString
 * @param cb
 */
const querySearch2 = (queryString: string, cb: (results: SelectOptionType[]) => any) => {
  // console.log(queryString)
  // const results: FormComponentProp[] = queryString
  //   ? restaurants.value.filter(createFilter(queryString))
  //   : restaurants.value
  cb(querySearch2List)
}

/**
 * 选择属性附带默认值
 * @param item
 * @param form
 * @param k
 */
const onQuerySelect2 = (
  item: SelectOptionType,
  form: BusinessUIQueryColumnType,
  k: string | number | undefined
) => {
  form.set_json_parse.props[String(k)] = item.value
}

const setJsonParse = (item: FormComponentProp, tag: string) => {
  set_json_parse_value.value = tag
  set_json_parse_key.value = item.value
}

const onFocus = (v: string, k: string | number | undefined) => {
  console.log('onFocus', v)
  querySearch2List.splice(0)
  const item = formComponentProps.find((f) => f.value === k)
  if (item && item.values) {
    item.values.forEach((v) => {
      v.values.forEach((k) => {
        querySearch2List.push({
          label: k,
          value: k
        })
      })
    })
  }
}

/**
 * @param queryString
 */
const createFilter = (queryString: string) => {
  return (restaurant: FormComponentProp) => {
    return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
  }
}

/**
 * 默认参数
 * @param form
 */
const onDefaultJson = (form: BusinessUIQueryColumnType) => {
  props.onEditJson(form.default_value_parse || {}, form.field)
}

/**
 * 是否是占位字段
 * @param form
 */
const isEmptyField = (form: BusinessUIQueryColumnType) => {
  return form.field.indexOf('empty_') !== -1
}

/**
 * 默认接口
 * @param queryString
 * @param cb
 */
const fetchUrls = (queryString: string, cb: any) => {
  // const results = queryString
  cb([
    { value: '/api-mis/OABusinessTrip/trip_days', method: 'get', description: '计算两个日期的天数' },
    { value: '/api-mis/AccountMember/supplier_info', method: 'get', description: '收款人银行详情' },
    { value: '/api-mis/AccountMember/customer_info', method: 'get', description: '付款单位银行详情' },
    { value: '/api-mis/Contract/contract_part_a', method: 'get', description: '合同甲方详情' },
    { value: '/api-mis/Contract/contract_part_b', method: 'get', description: '合同乙方详情' },
    { value: '/api-mis/Contract/contract_procurement_text', method: 'get', description: '合同类型提示' }
  ])
}

/**
 * 路劲改变
 * @param option
 * @param form
 */
const onUrlSelect = (option: TypedAny, form: BusinessUIQueryColumnType) => {
  if (option) {
    form.set_json_parse.method = option.method
  }
}

/**
 * 获取被联动的参数格式化
 */
const onLinkageChange = () => {
  const items = props.params.items || []
  items.forEach((form) => {
    const list = props.params.items.filter((f) => {
      const set_json_parse = f.set_json_parse || {}
      const linkage = set_json_parse.linkage || []
      return f.linkage && linkage.includes(form.field)
    })
    const convert: TypedAny = form.set_json_parse.convert || {}
    list.forEach((v) => {
      convert[v.field] = convert[v.field] || ''
    })
    form.set_json_parse.convert = list.length ? convert : undefined
  })
}

watch(
  () => props.params.items,
  () => {
    nextTick(onLinkageChange)
  },
  { immediate: true }
)
</script>

<template>
  <el-collapse v-model="activeName" accordion class="mb10">
    <el-collapse-item
      v-for="(form, index) in params.items"
      :key="index"
      :title="`${index + 1}、${form.field}`"
      :name="form.field"
    >
      <template #title>
        <div
          class="flex-grow flex align-center justify-between pl5 pr5"
          :class="{ 'collapse-active': form.field === active }"
          @click="active = form.field"
        >
          <div
            class="flex align-center"
            :class="{ 'color-warning': !form.component, pl20: !isEmptyField(form) }"
          >
            <el-icon size="20" class="mr5 color-primary" v-if="isEmptyField(form)">
              <Warning />
            </el-icon>
            <span class="mr5" v-else>{{ index + 1 }}. </span>
            <span v-if="form.required" class="font-bold font20 color-danger mt5 mr3">*</span>
            <span>{{ form.title || ' - - ' }}</span>
            <span class="ml3 mr3" v-if="!isEmptyField(form)">
              ({{ form.field }}{{ form.rel_item ? ` => ${form.rel_item}` : '' }})
            </span>
            <span v-if="!form.component" class="ml3 mr3"
              >({{ form.component ? '' : '未配置组件' }})</span
            >
          </div>
          <div class="flex align-center flex-warp mr5">
            <el-button
              :disabled="index <= 0"
              size="small"
              circle
              :icon="Top"
              @click.stop="onSplice(-1, index)"
            />
            <el-button
              :disabled="index >= params.items.length - 1"
              size="small"
              circle
              :icon="Bottom"
              @click.stop="onSplice(1, index)"
              class="ml10"
            />
            <el-button
              size="small"
              type="danger"
              circle
              :icon="Delete"
              @click.stop="onDeleteForm(index)"
              class="ml10"
            />
          </div>
        </div>
      </template>
      <el-row :gutter="10" class="pl10 pr10 mt10">
        <el-col class="mb5">
          <el-cascader
            style="width: 400px"
            v-model="form.component"
            placeholder="选择组件"
            :options="formComponentOptions"
            @change="onSelectComponent($event, form)"
            clearable
            filterable
            class="flex-grow"
          />
          <el-link
            v-if="getDocument(form)"
            :href="getDocument(form)"
            target="_blank"
            type="primary"
            class="ml10 flex-shrink"
          >
            文档地址
          </el-link>
        </el-col>
        <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
          <div class="mb5">
            <div class="pl10 flex-shrink">中文标题：{{ form.field }}</div>
            <el-input clearable type="text" v-model="form.title" placeholder="标题名称" />
          </div>
          <div v-if="['custom-pre'].includes(form.component)" class="mb5">
            <el-input
              v-model="form.set_json_parse.description"
              type="textarea"
              rows="5"
              placeholder="请输入文本"
            />
          </div>
          <div class="mb5" v-if="customComponents.includes(form.component)">
            <span class="pl10">关联的业务：</span>
            <div class="flex align-center">
              <el-tree-select
                v-model="form.business_id"
                filterable
                default-expand-all
                :data="business"
                value-key="id"
                placeholder="选择业务"
                :props="{ label: 'title' }"
              />
              <el-button @click="onDefaultJson(form)" type="warning" class="ml10"
                >默认参数
              </el-button>
            </div>
          </div>
          <div class="flex align-center mb5">
            <div class="pl10 flex-shrink">显示字段：</div>
            <el-select v-model="form.rel_item" placeholder="详情显示字段" filterable clearable>
              <el-option
                v-for="(item, index) in columns"
                :key="index"
                :label="item.name"
                :value="item.name"
              />
            </el-select>
          </div>
          <div class="flex align-center">
            <div class="pl10 flex-shrink">格式类型：</div>
            <el-select v-model="form.set_json_parse.formatType" placeholder="格式化配置" clearable>
              <el-option
                v-for="item in formatOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </div>
          <div class="flex align-center">
            <div class="pl10 flex-shrink">是否必填：</div>
            <el-switch
              v-model="form.required"
              inline-prompt
              active-text="是否必填"
              inactive-text="是否必填"
            />
          </div>
          <div class="flex align-center" v-if="!customComponents.includes(form.component)">
            <div class="pl10 flex-shrink">编辑禁用：</div>
            <el-switch
              v-model="form.disable_on_edit"
              inline-prompt
              active-text="编辑禁用"
              inactive-text="编辑禁用"
            />
          </div>
          <div class="flex align-center" v-if="!customComponents.includes(form.component)">
            <div class="pl10 flex-shrink">是否联动：</div>
            <el-switch
              v-model="form.linkage"
              inline-prompt
              active-text="是否联动"
              inactive-text="是否联动"
            />
          </div>

          <div v-if="form.linkage" class="flex align-center mb5">
            <div class="pl10 flex-shrink">联动字段：</div>
            <el-select
              v-model="form.set_json_parse.linkage"
              multiple
              placeholder="选择联动时需要变化的字段"
              filterable
              clearable
              @change="onLinkageChange"
            >
              <el-option
                v-for="(item, index) in params.items"
                :key="index"
                :label="item.title || item.field"
                :value="item.field"
              />
            </el-select>
          </div>
          <div class="flex align-center flex-warp mb5" v-if="form.set_json_parse.convert">
            <div class="pl10 flex-shrink">参数转换：</div>
            <div
              v-for="(v, k, i) in form.set_json_parse.convert"
              :key="i"
              class="flex align-center mr5"
            >
              <span class="mr5">{{ k }} => </span>
              <el-input
                v-model="form.set_json_parse.convert[k]"
                style="width: 100px"
                placeholder="转换后的参数名"
              />
            </div>
          </div>
          <div class="flex align-center">
            <div class="pl10 flex-shrink">接口获取：</div>
            <el-switch
              v-model="form.is_api"
              inline-prompt
              active-text="是否接口获取"
              inactive-text="是否接口获取"
            />
          </div>
          <div v-if="form.is_api" class="flex align-center mb5">
            <div class="pl10 flex-shrink">接口地址：</div>
            <!--            <el-input v-model="form.set_json_parse.url" placeholder="接口" clearable/>-->
            <el-autocomplete
              style="width: 100%"
              v-model="form.set_json_parse.url"
              :fetch-suggestions="fetchUrls"
              clearable
              placeholder="接口"
              @select="onUrlSelect($event, form)"
            >
              <template #default="{ item }">
                <div class="value">{{ item.value }}（{{ item.description }}）</div>
              </template>
            </el-autocomplete>
            <el-select
              v-model="form.set_json_parse.method"
              placeholder="请求方法"
              style="width: 70px"
              class="flex-shrink ml5"
              clearable
            >
              <el-option label="GET" value="get" />
              <el-option label="POST" value="post" />
              <el-option label="PUT" value="put" />
              <el-option label="DELETE" value="delete" />
            </el-select>
            <el-button @click="onDefaultJson(form)" type="warning" class="ml5">默认参数</el-button>
          </div>
          <div class="mb5">
            <el-input-number size="small" v-model="form.set_json_parse.col.xs" :min="1" :max="24" />
            <span class="ml10">xs &lt;768px</span>
          </div>
          <div class="flex align-center mr10 mb5">
            <el-input-number size="small" v-model="form.set_json_parse.col.sm" :min="1" :max="24" />
            <span class="ml10">sm ≥768px</span>
          </div>
          <div class="flex align-center mr10 mb5">
            <el-input-number size="small" v-model="form.set_json_parse.col.md" :min="1" :max="24" />
            <span class="ml10">md ≥992px</span>
          </div>
          <div class="flex align-center mr10 mb5">
            <el-input-number size="small" v-model="form.set_json_parse.col.lg" :min="1" :max="24" />
            <span class="ml10">lg ≥1200px</span>
          </div>
          <div class="flex align-center mr10 mb5">
            <el-input-number size="small" v-model="form.set_json_parse.col.xl" :min="1" :max="24" />
            <span class="ml10">xl ≥1920px</span>
          </div>
        </el-col>
        <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
          <el-card shadow="hover">
            <div class="mb10">
              <div class="text-capitalize mb5 color-info font16">
                {{ form.component }} 组件属性拓展
              </div>
              <div class="flex align-center">
                <el-autocomplete
                  size="small"
                  style="width: 50%"
                  v-model="set_json_parse_key"
                  :fetch-suggestions="querySearch"
                  clearable
                  placeholder="属性名"
                  @select="onQuerySelect"
                >
                  <template #default="{ item }">
                    <div class="value">
                      <span class="color-primary">{{ item.value }}</span>
                      <span>（{{ item.label }}）</span>
                    </div>
                    <div v-if="item.values" style="line-height: 22px">
                      <div v-for="(row, idx) in item.values" :key="idx" class="font14">
                        <i class="font12 color-info">{{ row.title }}：</i>
                        <el-tag
                          size="small"
                          effect="plain"
                          type="warning"
                          class="mr3"
                          v-for="tag in row.values"
                          :key="tag"
                          @click.stop="setJsonParse(item, tag)"
                          >{{ tag }}
                        </el-tag>
                      </div>
                    </div>
                    <div v-else class="color-info" style="white-space: pre; line-height: 20px">
                      {{ item.type }}
                    </div>
                  </template>
                </el-autocomplete>
                <el-input
                  size="small"
                  style="width: 50%"
                  v-model="set_json_parse_value"
                  placeholder="值"
                  class="ml5"
                  clearable
                />
                <el-button type="success" text :icon="Plus" @click="addProp(form)" class="ml5"
                  >新增属性
                </el-button>
              </div>
            </div>
            <div v-for="(v, k) in form.set_json_parse.props" :key="k">
              <div class="flex align-center mb5">
                <div class="flex-shrink text-right pr10" style="width: 40%">{{ k }}</div>
                <!--                <el-input size="small" v-model="form.set_json_parse.props[k]" placeholder="值"/>-->
                <el-autocomplete
                  size="small"
                  v-model="form.set_json_parse.props[k]"
                  :fetch-suggestions="querySearch2"
                  clearable
                  placeholder="值"
                  @select="onQuerySelect2($event, form, k)"
                  @focus="onFocus(v, k)"
                  class="flex-grow"
                >
                  <template #default="{ item }">
                    <span>{{ item.value }}</span>
                  </template>
                </el-autocomplete>
                <el-button
                  size="small"
                  :icon="Close"
                  circle
                  class="ml10"
                  @click="onDeleteProp(form, String(k))"
                />
              </div>
            </div>
            <template #footer v-if="!customComponents.includes(form.component)">
              <div class="flex align-center">
                <span class="color-info">组件属性请参阅：</span>
                <el-link :href="getDocument(form)" target="_blank" type="primary">
                  文档地址
                </el-link>
              </div>
            </template>
          </el-card>
        </el-col>
      </el-row>
    </el-collapse-item>
  </el-collapse>
</template>

<style scoped lang="scss">
.collapse-active {
  background-color: var(--el-color-primary-light-9) !important;
}
</style>
